package component

import (
	"bytes"
	"fmt"
)

type Col struct{
	Width int
	Label string
	Field string
	IsIndex bool
	TextAlign string
	FixedEnd bool
	FixedStart bool
	Render func(index int,col *Col,item map[string]any) string
}
type Table struct{
	Cols []*Col
	Data []map[string]any
	FixEndCols []*Col
	FixStartCols []*Col
	Footer string
}
func NewTable(cols ...*Col) *Table{
	tb:= &Table{
		Cols:cols,
		FixEndCols: make([]*Col,0),
		FixStartCols: make([]*Col,0),
	}
	for _, col := range cols {
		if col.FixedEnd {
			tb.FixEndCols = append(tb.FixEndCols,col)
		}
		if col.FixedStart {
			tb.FixStartCols = append(tb.FixStartCols,col)
		}
		if col.Render==nil {
			col.Render = func(index int,col *Col,item map[string]any) string {
				if col.IsIndex{
					return fmt.Sprintf(`%d`,index+1)
				}
				val,_:=item[col.Field]
				return fmt.Sprintf(`%v`,val)
			}
		}
	}
	return tb
}
func (t *Table) AddCol(col *Col){
	t.Cols = append(t.Cols,col)
}
//setData
func (t *Table) SetData(data []map[string]any)  {
	t.Data = data
}


func (t *Table) Render() string  {
	html:=bytes.NewBufferString(`<div class="table">`)
	html.WriteString(`<div class="thead" _="on scrollX set my scrollLeft to detail.sender.scrollLeft
    on hasScrollBar set my style.paddingRight to '6px'">`)
	html.WriteString(`<table>`)
	html.WriteString(`<colgroup>`)
	for _,col := range t.Cols{
		html.WriteString(fmt.Sprintf(`<col style="width:%dpx"/>`,col.Width))
	}
	html.WriteString(`</colgroup>`)
	html.WriteString(`<thead>`)
	html.WriteString(`<tr>`)
	for _,col := range t.Cols{
		html.WriteString(fmt.Sprintf(`<th>%s</th>`,col.Label))
	}
	html.WriteString(`</tr>`)
	html.WriteString(`</thead>`)
	html.WriteString(`</table>`)
	html.WriteString(`</div>`)
	html.WriteString(`<div class="tbody" _="init if my.scrollHeight > my.clientHeight
        send hasScrollBar to <.table .thead/> end
    on scroll send scrollX to <.table .thead/>
    on hasFoot set my style.height to 'calc(100% - 70px)'
    on resized wait 0s
    set offsetHeight to my.offsetHeight
    if my.scrollWidth > my.clientWidth set offsetHeight to (offsetHeight - 7) end
    set rect to my getBoundingClientRect()
    send setwh(rect:rect,offsetHeight:offsetHeight) to <.fixedEnd/> in me
    ">`)
	if len(t.FixEndCols)>0 {
		html.WriteString("<div class=\"fixedEnd\" _=\"on setwh(rect,offsetHeight) set :oh to offsetHeight set w to my offsetWidth set :L to (rect.right - w) then set my *height to `${:oh}px` set my *left to `${:L}px`\">")
		for ii,item := range t.Data {
			for _, col := range t.FixEndCols {
				html.WriteString(fmt.Sprintf(`<div class="td" style="width:%dpx">`,col.Width-1))
				html.WriteString(col.Render(ii,col,item))
				html.WriteString(`</div>`)
			}
		}
	}
	html.WriteString(`<table>`)
	html.WriteString(`<colgroup>`)
	for _,col := range t.Cols{
		html.WriteString(fmt.Sprintf(`<col style="width:%dpx"/>`,col.Width))
	}
	html.WriteString(`</colgroup>`)
	html.WriteString(`<tbody>`)
	for ii,item:= range t.Data {
		html.WriteString(`<tr>`)
		for _,col := range t.Cols{
			align:=""
			if col.TextAlign!="" {
				align = fmt.Sprintf(` align="%s"`,col.TextAlign)
			}
			html.WriteString(fmt.Sprintf(`<td%s>`,align))
			html.WriteString(col.Render(ii,col,item))
			html.WriteString(`</td>`)
		}
		html.WriteString(`</tr>`)
	}
	html.WriteString(`</tbody>`)
	html.WriteString(`</table>`)
	if t.Footer!="" {
		html.WriteString(`<div class="tfoot" _="init send hasFoot to <.table .tbody/>">`)
		html.WriteString(t.Footer)
		html.WriteString(`</div>`)
	}
	html.WriteString(`</div>`)
	return html.String()
}